package cn.wolfcode.p2p.bussness.service.impl;

import cn.wolfcode.p2p.base.domain.Account;
import cn.wolfcode.p2p.base.exception.DisplayableException;
import cn.wolfcode.p2p.base.query.QueryObject;
import cn.wolfcode.p2p.base.service.IAccountService;
import cn.wolfcode.p2p.base.util.Constants;
import cn.wolfcode.p2p.base.util.UserContext;
import cn.wolfcode.p2p.bussness.domain.*;
import cn.wolfcode.p2p.bussness.mapper.PaymentScheduleMapper;
import cn.wolfcode.p2p.bussness.service.*;
import cn.wolfcode.p2p.bussness.util.CalculatetUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class PaymentScheduleServiceImpl implements IPaymentScheduleService {

    @Autowired
    private PaymentScheduleMapper paymentScheduleMapper;

    @Autowired //账户信息
    private IAccountService accountService;

    @Autowired //账户流水信息
    private IAccountFlowService accountFlowService;

    @Autowired //系统账户信息
    private ISystemAccountService systemAccountService;

    @Autowired //系统账户流水信息
    private ISystemAccountFlowService systemAccountFlowService;

    @Autowired //还款计划明细
    private IPaymentScheduleDetailService paymentScheduleDetailService;

    @Autowired //借款对象
    private IBidRequestService bidRequestService;

    @Autowired //投标对象
    private IBidService bidService;

    @Autowired
    private IExpAccountService expAccountService;

    @Autowired
    private IExpAccountFlowService expAccountFlowService;

    @Override
    public int save(PaymentSchedule paymentSchedule) {
        return paymentScheduleMapper.insert(paymentSchedule);
    }

    @Override
    public int update(PaymentSchedule paymentSchedule) {
        return paymentScheduleMapper.updateByPrimaryKey(paymentSchedule);
    }

    @Override
    public PaymentSchedule get(Long id) {
        return paymentScheduleMapper.selectByPrimaryKey(id);
    }

    @Override
    public PageInfo queryPage(QueryObject qo) {
        PageHelper.startPage(qo.getPageNum(), qo.getPageSize());
        List<PaymentSchedule> list = paymentScheduleMapper.selectList(qo);
        return new PageInfo(list);
    }

    @Override
    public void returnMoney(Long id) {
        PaymentSchedule paymentSchedule = this.get(id);
        //得到还款对象
        BidRequest bidRequest = bidRequestService.get(paymentSchedule.getBidRequestId());

        //根据ID 查询还款对象 判断还款对象是否处于 正常待还的状态
        if (paymentSchedule != null && paymentSchedule.getState() == Constants.PAYMENT_STATE_NORMAL) {
            //获取当前登陆用户的账户信息
            Account account = accountService.get(UserContext.getCurrent().getId());

            //系统账户信息
            SystemAccount systemAccount = systemAccountService.get();
            if (
                    paymentSchedule != null &&
                            ((
                                    bidRequest.getBidRequestType() == Constants.BIDREQUEST_TYPE_NORMAL && //当前借款对象的类型是信用标
                                            account.getId().equals(paymentSchedule.getBorrowUser().getId()) && //确认当前账户与登陆用户是同一个人
                                            account.getUsableAmount().compareTo(paymentSchedule.getTotalAmount()) >= 0) //当前账户的可用金额 >= 当期的还款金额
                                    ||
                                    (
                                            bidRequest.getBidRequestType() == Constants.BIDREQUEST_TYPE_EXP && //当前借款对象的类型是体验标
                                                    systemAccount.getUsableAmount().compareTo(paymentSchedule.getInterest()) >= 0 //系统账户的余额 >= 所欠款的利息 本金不用算
                                    )
                            )
                    ) {

                //设置还款日期
                paymentSchedule.setPayDate(new Date());
                //设置还款状态 --> 已还款
                paymentSchedule.setState(Constants.PAYMENT_STATE_DONE);
                //更新到数据库
                this.update(paymentSchedule);
                //还款明细设置还款时间
                paymentScheduleDetailService.updatePayDate(paymentSchedule.getId(), paymentSchedule.getPayDate());

                //如果是信用标
                if (bidRequest.getBidRequestType() == Constants.BIDREQUEST_TYPE_NORMAL) {
                    //对于还款人
                    //可用金额减少
                    account.setUsableAmount(account.getUsableAmount().subtract(paymentSchedule.getTotalAmount()));
                    //待还本息减少
                    account.setUnReturnAmount(account.getUnReturnAmount().subtract(paymentSchedule.getTotalAmount()));
                    //剩余授信额度增加 = 原剩余授信额度 + 本金
                    account.setRemainBorrowLimit(account.getRemainBorrowLimit().add(paymentSchedule.getPrincipal()));
                    //更新到数据库
                    accountService.update(account);
                    //生成还款成功流水
                    accountFlowService.createRechargeOfflineFlow(account, paymentSchedule.getTotalAmount(), "还款成功: " + paymentSchedule.getTotalAmount() + "元",
                            Constants.ACCOUNT_ACTIONTYPE_RETURN_MONEY);
                } else if (bidRequest.getBidRequestType() == Constants.BIDREQUEST_TYPE_EXP) {
                    //如果是体验标
                    //可用资金减少 = 原来的可用资金 - 要付款的利息  因为是系统账户 不用付手续费
                    systemAccount.setUsableAmount(systemAccount.getUsableAmount().subtract(Constants.ZERO));
                    //保存到数据库
                    systemAccountService.save(systemAccount);
                    //生成还款成功的流水
                    systemAccountFlowService.createGainAccountManagementChargeSuccessFlow(systemAccount, Constants.ZERO);
                }

                //对于投资人
                //遍历还款明细
                Map<Long, Account> accountMap = new HashMap<>();
                //投资人的体验金
                Map<Long, ExpAccount> expAccountMap = new HashMap<>();
                Account bidUserAccount;
                ExpAccount bidUserExpAccount;
                Long bidUserId;
                List<PaymentScheduleDetail> details = paymentSchedule.getDetails();
                //遍历明细
                for (PaymentScheduleDetail psd : details) {
                    bidUserId = psd.getInvestorId();
                    bidUserAccount = accountMap.get(bidUserId);
                    bidUserExpAccount = expAccountMap.get(bidUserId);

                    //如果投资人账户信息为null
                    if (bidUserAccount == null) {
                        bidUserAccount = accountService.get(bidUserId);
                        accountMap.put(bidUserId, bidUserAccount);
                        bidUserExpAccount = expAccountService.get(bidUserId);
                        expAccountMap.put(bidUserId, bidUserExpAccount);
                    }
                    //如果是信用标
                    if (bidRequest.getBidRequestType() == Constants.BIDREQUEST_TYPE_NORMAL) {
                        //投资人可用余额增加 = 原本的可用余额 + 新加进来的可用余额,
                        bidUserAccount.setUsableAmount(bidUserAccount.getUsableAmount().add(psd.getTotalAmount()));
                        // 生成收款成功流水
                        accountFlowService.createRechargeOfflineFlow(bidUserAccount, psd.getTotalAmount(), "收款成功: " + psd.getTotalAmount() + "元",
                                Constants.ACCOUNT_ACTIONTYPE_CALLBACK_MONEY);
                        //待收本金减少
                        bidUserAccount.setUnReceivePrincipal(bidUserAccount.getUnReceivePrincipal().subtract(psd.getPrincipal()));
                    } else {
                        //体验标 体验金账户增加
                        bidUserExpAccount.setUsableAmount(bidUserExpAccount.getUsableAmount().add(psd.getPrincipal()));
                        //生成体验金增加 的流水
                        expAccountFlowService.createExpAccountFlow(bidUserExpAccount, psd.getPrincipal());
                        //系统账户支付利息 =  可用 - 支付利息
                        systemAccount.setUsableAmount(systemAccount.getUsableAmount().subtract(psd.getInterest()));
                        //生成系统账户支付流水
                        systemAccountFlowService.createGainAccountManagementChargeSuccessFlow(systemAccount, psd.getInterest());
                        //投资人收取利息
                        bidUserAccount.setUsableAmount(bidUserAccount.getUsableAmount().add(psd.getInterest()));
                        //投资人账户生成流水
                        accountFlowService.createRechargeOfflineFlow(bidUserAccount, psd.getInterest(), "收取利息: " + psd.getInterest() + "元"
                                , Constants.EXPACCOUNT_ACTIONTYPE_CALLBACK_MONEY);
                    }

                    //待收利息 减少 = 原本的利息 - 新的利息
                    bidUserAccount.setUnReceiveInterest(bidUserAccount.getUnReceiveInterest().subtract(psd.getInterest()));

                    //平台利息管理费
                    BigDecimal interestManagerCharge = CalculatetUtil.calInterestManagerCharge(psd.getInterest());

                    //账户支付平台利息管理费
                    bidUserAccount.setUsableAmount(bidUserAccount.getUsableAmount().subtract(interestManagerCharge));

                    //生成支付利息流水
                    accountFlowService.createRechargeOfflineFlow(bidUserAccount, interestManagerCharge, "支付利息: " + interestManagerCharge + "元",
                            Constants.ACCOUNT_ACTIONTYPE_INTEREST_SHARE);


                    //平台收取利息管理费,生成收取利息流水
                    systemAccount.setUsableAmount(systemAccount.getUsableAmount().add(interestManagerCharge));
                    //生成流水
                    systemAccountFlowService.createGainAccountManagementChargeFlow(systemAccount, interestManagerCharge);
                }

                //对普通账户统一修改
                for (Account accounts : accountMap.values()) {
                    accountService.update(accounts);
                }

                //对体验金账户统一修改
                for (ExpAccount expAccount : expAccountMap.values()) {
                    //改变
                    expAccountService.update(expAccount);
                }


                //对系统账户统一的修改
                systemAccountService.update(systemAccount);

                //判断还款是否还清 根据借款ID 查询所有的借款对象
                List<PaymentSchedule> paymentSchedules = this.paymentScheduleMapper.queryByBidRequestId(paymentSchedule.getBidRequestId());

                for (PaymentSchedule ps : paymentSchedules) {
                    if (ps.getState() != Constants.PAYMENT_STATE_DONE) {
                        //如果能进到这里面 证明还没有还清
                        return;
                    }
                }

                //设置状态 已还清
                bidRequest.setBidRequestState(Constants.BIDREQUEST_STATE_COMPLETE_PAY_BACK);
                //更新到数据库
                bidRequestService.update(bidRequest);
                //借款对象 和 投标对象 设置成已完成
                bidService.updateState(bidRequest.getId(), Constants.BIDREQUEST_STATE_COMPLETE_PAY_BACK);
            } else {
                throw new DisplayableException("非法参数");
            }
        } else {
            throw new DisplayableException("非法参数");
        }
    }
}
